package com.wyz.socket.core.base.frame;

import com.wyz.socket.core.base.IoArgs;

import java.io.IOException;

public abstract class Frame {
    public static final int FRAME_HEADER_LENGTH = 6;
    public static final int MAX_CAPACITY = 64 * 1024 - 1;

    // type
    public static final byte TYPE_HEADER = 11;
    public static final byte TYPE_ENTITY = 12;

    public static final byte TYPE_SEND_CANCEL = 21;
    public static final byte TYPE_RECEIVE_REJECT = 22;

    // 心跳类型
    public static final byte TYPE_HEARTBEAT = 81;

    // flag
    public static final byte FLAG_NON = 0;
    protected final byte[] header = new byte[FRAME_HEADER_LENGTH];

    public Frame(int length, /*0-15*/
                 byte type, /*16-23*/
                 byte flag, /*24-31*/
                 short identifier /*31*/) {
        if (length < 0 || length > MAX_CAPACITY) {
            throw new RuntimeException("Frame length is error = " + length);
        }
        if (identifier < 1 || identifier > 255) {
            throw new RuntimeException("Frame identifier is error = " + identifier);
        }
        // 0 - 15  length ,  0-7 length hight , 8-15 length lower
        header[0] = (byte) (length >> 8);
        header[1] = (byte) length;

        header[2] = type;
        header[3] = flag;

        header[4] = (byte) identifier;
        header[5] = 0; // other
    }

    public Frame(byte[] header){
        System.arraycopy(header , 0 , this.header , 0 , FRAME_HEADER_LENGTH);
    }

    public int getBodyLength() {
        return ((((int) header[0]) & 0xff) << 8) | (((int) header[1]) & 0xff);
    }

    public byte getBodtType() {
        return header[2];
    }

    public byte getBodyFlag() {
        return header[3];
    }

    public short getBodyIdentifier() {
        return (short) (((short) header[4]) & 0xff);
    }

    public byte getOther(){
        return header[5] ;
    }

    public abstract boolean handle(IoArgs args) throws IOException;

    public abstract Frame nextFrame() ;

    public abstract int getUnConsumeLength();
}
